'''
文件：comprehensiveEd.py
时间：2021-5-26 11:20AM
作者：邓鉴
版本：1.0
最新编辑者：无
最新编辑时间：无
联系方式：dengjian@ynao.ac.cn
作用：湍流数据库设计
'''
import sys
import pymysql
import csv
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QFileDialog
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery, QSqlQueryModel
from PyQt5.QtCore import Qt, QDateTime, QItemSelectionModel, pyqtSlot, QDir
from oTableView import Ui_MainWindow #导入界面
from MyDelegates import QMyDateTimeEdit
from picture import SonWindow        #因为直接显示数据作图有问题，所以新开了个界面来展示数据作图
import numpy as np
import pyqtgraph as pg

class MyMainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()  #继承界面
        self.ui.setupUi(self)
        self.init_date()           #初始化当前时间，用于设定界面中的dateTimeEdit控件
        self.biteOpen = 0          #判断数据库是否开启
        pg.setConfigOption('background','w')    #用于设置pg绘图的背景
        pg.setConfigOption('foreground', 'k')
        self.ui.pushButton_search.setEnabled(False)    #这几个按钮先设置为无效，等数据库打开再设置为有效
        self.ui.pushButton_export.setEnabled(False)
        self.ui.pushButton_delete.setEnabled(False)

    def __del__(self):
        #当对象销毁时，数据库打开的话，将数据库关闭
        if self.biteOpen == 1:
            self.db.close()

    def init_date(self):
        # 初始化当前时间，用于设定界面中的dateTimeEdit控件
        currDateTime = QDateTime.currentDateTime()
        self.ui.dateTimeEdit.setDateTime(currDateTime.addDays(-1))
        self.ui.dateTimeEdit_2.setDateTime(currDateTime)

    def on_pushButton_open_pressed(self):
        #开启数据库
        #print(self.ui.comboBox_selecttable.currentText(),type(self.ui.comboBox_selecttable.currentText()))    #用于判断已选择的数据库
        self.init_sql()    #初始化数据库

    def init_sql(self):
        #初始化数据库
        if self.biteOpen == 0:    #判断数据库是否开启，0为没有开启，1为开启；没有起就开启
            self.db = QSqlDatabase.addDatabase('QMYSQL') #加载数据库驱动
            self.db.setHostName('127.0.0.1')
            self.db.setPort(3306)
            self.db.setUserName('root')
            self.db.setPassword('123456')
            self.db.setDatabaseName('demodb')
            self.db.open()
            self.biteOpen = 1    #数据库判断位设置为1
        if self.db.open():
            print('成功打开数据库')
            self.ui.pushButton_search.setEnabled(True)  # 数据库打开后，设置搜索按钮可用
            self.__openTable(self.ui.comboBox_selecttable.currentText())    #传入选择框的当前数据，用于选择开启的数据库
        else:
            QMessageBox.warning(self, '错误', '打开数据库失败!!!\n'+self.db.lastError().text())

        self.query = QSqlQuery()    #pyqt执行各种SQL语句的类

    def __openTable(self, tableName):
        #根据传入的数据库名，打开特定的数据库
        self.qryModel = QSqlQueryModel(self)   #pyqt的SQL只读数据模型类，与ui中tableview绑定来显示查询的数据
        if tableName == '质心表':
            print('进入质心表')
            self.qryModel.setQuery('''SELECT * FROM centriod''')   #查询数据库的centriod(质心)表
            if self.qryModel.lastError().isValid():
                QMessageBox.critical(self, '错误', '数据表查询错误，出错信息为\n'+self.qryModel.lastError().text())
                return
            #设置model的表头
            self.qryModel.setHeaderData(0, Qt.Horizontal, '时间')
            self.qryModel.setHeaderData(1, Qt.Horizontal, '质点1，x坐标')
            self.qryModel.setHeaderData(2, Qt.Horizontal, '质点1，y坐标')
            self.qryModel.setHeaderData(3, Qt.Horizontal, '质点2，x坐标')
            self.qryModel.setHeaderData(4, Qt.Horizontal, '质点2，y坐标')

            # self.selModel = QItemSelectionModel(self.qryModel)
            # self.selModel.currentRowChanged.connect(self.do_currentRowChanged)

            # 因为tableView的默认模型不能展示毫秒，所以对其行进行数据的改写
            self.ui.tableView.setItemDelegateForColumn(0, QMyDateTimeEdit(self))
            self.ui.tableView.setModel(self.qryModel)    #绑定tableView和model（模型）

        elif tableName == '数据表':  #如果是数据表，这里对数据表进行查询，需要设定相关的内容
            print('进入数据表')
            #设定查询内容
            self.qryModel.setQuery('''SELECT EmpNo,Name,Gender,Birthday,Province,Department FROM employee''')
            if self.qryModel.lastError().isValid():    #如果查询有问题，就报错
                QMessageBox.critical(self, '错误', '数据表查询错误，出错信息为\n' + self.qryModel.lastError().text())
                return

            #设定表头
            self.qryModel.setHeaderData(0, Qt.Horizontal, '职工编号')
            self.qryModel.setHeaderData(1, Qt.Horizontal, '名字')
            self.qryModel.setHeaderData(2, Qt.Horizontal, '性别')
            self.qryModel.setHeaderData(3, Qt.Horizontal, '生日')
            self.qryModel.setHeaderData(4, Qt.Horizontal, '省份')
            self.qryModel.setHeaderData(5, Qt.Horizontal, '学院')


            # self.selModel = QItemSelectionModel(self.qryModel)
            # self.selModel.currentRowChanged.connect(self.do_currentRowChanged)

            # self.ui.tableView.setItemDelegateForColumn(0, QMyDateTimeEdit(self))
            self.ui.tableView.setModel(self.qryModel)    #将tableView和model（模型）绑定

    def on_pushButton_search_pressed(self):
        #查询按钮
        self.ui.pushButton_export.setEnabled(True)   #查询按钮起效后，设置导出和删除按钮可用
        self.ui.pushButton_delete.setEnabled(True)
        initTime = self.ui.dateTimeEdit.dateTime().toString('yyyy-MM-dd hh:mm:ss')    #查询界面中dateTimeEdit的日期后将其转化为字符串模式
        endTime = self.ui.dateTimeEdit_2.dateTime().toString('yyyy-MM-dd hh:mm:ss')
        #通过查询模型，根据时间节点查询内容
        self.qryModel.setQuery("SELECT * FROM centriod WHERE datetime BETWEEN '%s' AND '%s'" %(initTime,endTime))

    def on_pushButton_delete_pressed(self):
        #删除按钮
        initTime = self.ui.dateTimeEdit.dateTime().toString('yyyy-MM-dd hh:mm:ss')    #凭借着时间节点删除数据库内容
        endTime = self.ui.dateTimeEdit_2.dateTime().toString('yyyy-MM-dd hh:mm:ss')
        #消息窗口，用来确定是否确定删除，这里要加这一步，主要还是考虑到了防止误删数据库。
        #返回两个值，QMessageBox.Yes(确定删除)和QMessageBox.No(取消删除）
        select = QMessageBox.warning(self, '警告', '警告：\n'+'你将删除 %s 至 %s 的数据!' %(self.ui.dateTimeEdit.dateTime().toString('yyyy年MM月dd日hh时mm分ss秒'),
                                      self.ui.dateTimeEdit_2.dateTime().toString('yyyy年MM月dd日hh时mm分ss秒'))
                                                                              , QMessageBox.Yes | QMessageBox.No)
        if select == QMessageBox.Yes:   #确定删除
            self.query.prepare("DELETE FROM centriod WHERE datetime BETWEEN :inittime AND :endtime")
            self.query.bindValue(':inittime', initTime)
            self.query.bindValue(':endtime', endTime)
            self.query.exec()
            if self.query.exec() == False:    #如果删除语句执行有误，就报错
                QMessageBox.critical(self, '错误', '删除记录出现错误\n'+self.query.lastError().text())
            else:   #删除语句执行正常后刷新界面
                sqlStr = self.qryModel.query().executedQuery()
                self.qryModel.setQuery(sqlStr)
        else:    #取消删除
            QMessageBox.information(self, '提示', '已取消删除数据')

    def __getFieldNames(self):
        emptyRec = self.tabModel.record() #获取只有字段名的，空记录表
        self.fldNum = {}
        for i in range(emptyRec.count()):
            fieldName = emptyRec.fieldName(i)   #得到字段名的名字，
            self.fldNum.setdefault(fieldName)   #设置字典的关键字
            self.fldNum[fieldName] = i          #关键字对应的值，值得type为数字

    # def on_pushButton_search_pressed(self):
    #     # print(self.ui.dateEdit.dateTime())
    #     try:
    #         initTime = self.ui.dateTimeEdit.dateTime()
    #         endTime = self.ui.dateTimeEdit_2.dateTime()
    #         if initTime < endTime:
    #             print(initTime.toString('yyyy-MM-dd hh:mm:ss'), endTime.toString('yyyy-MM-dd hh:mm:ss'))
    #             self.query.prepare("SELECT * FROM centriod WHERE datetime BETWEEN :inittime AND :endtime")
    #             self.query.bindValue(':inittime', initTime)
    #             self.query.bindValue(':endtime', endTime)
    #             self.query.exec()
    #             while self.query.next():
    #                 print(self.query.value('datetime'))
    #         else:
    #             QMessageBox.warning(self,'错误信息','搜索时间设置有问题，请重新设置')
    #     except:
    #         QMessageBox.warning(self, '错误', '请先打开数据库!!!')



    def on_pushButton_export_pressed(self):
        #导出数据，这里面之所以用pymysql，主要还是我不会使用pyqt自带的数据库内容进行数据处理
        #这里需要添加一个机制，只有在查询完数据之后再进行导出，或者就是全部导出
        #还是使用，导出当前数据或者导出全部数据的设定呢？
        def query_all(cur, sql, args):   #这里主要还是为了执行抓取内容的语句
            cur.execute(sql, args)
            return cur.fetchall()

        initTime = self.ui.dateTimeEdit.dateTime().toString('yyyy-MM-dd-hh_mm_ss')   #定义要抓取数据的时间
        endTime = self.ui.dateTimeEdit_2.dateTime().toString('yyyy-MM-dd-hh_mm_ss')

        filename = initTime + 'to' + endTime + '.csv'   #根据抓取的时间来为文件夹命名，这里是将文件保存为CSV文件，方便以后的数据处理
        curPath = filename
        dlgTitle = '保存文件'
        filt = '所有文件(*.*);;CSV文件(*.csv)'
        filename, filtUsed = QFileDialog.getSaveFileName(self, dlgTitle, curPath, filt)   #调用QFileDialog模块，选择要存储的路径

        with open(filename,'w',encoding='utf-8') as f:   #将查询到的内容存储到CSV文件中
            write = csv.writer(f, dialect='excel')
            write.writerow(('时间', '质心1(x坐标)','质心1(y坐标)','质心2(x坐标)','质心2(y坐标)'))    #定义第一行数据，即表头
            conn = pymysql.connect(host='localhost', port=3306, user='root', passwd='123456', db='demodb', charset='utf8')
            cur = conn.cursor()
            sql = "SELECT * FROM centriod WHERE datetime BETWEEN '%s' AND '%s'" %(initTime,endTime)
            results = query_all(cur=cur, sql=sql, args=None)
            if results == tuple():
                QMessageBox.information(self, '未查询到记录','当前时间段 %s 至 %s 没有记录，请重新查询!'
                                    %(self.ui.dateTimeEdit.dateTime().toString('yyyy年MM月dd日hh时mm分ss秒'),
                                      self.ui.dateTimeEdit_2.dateTime().toString('yyyy年MM月dd日hh时mm分ss秒')))
                return
            for result in results:
                write.writerow(result)
        QMessageBox.information(self, '保存成功','文件已被保存至%s'%filename)

    @pyqtSlot()
    def on_pushButton_draw_clicked(self):
        #对选中的数据进行绘图
        def query_all(cur, sql, args):   #抓取数据
            cur.execute(sql, args)
            return cur.fetchall()
        initTime = self.ui.dateTimeEdit.dateTime().toString('yyyy-MM-dd hh:mm:ss')    #设置查询的日期
        endTime = self.ui.dateTimeEdit_2.dateTime().toString('yyyy-MM-dd hh:mm:ss')
        conn = pymysql.connect(host='localhost', port=3306, user='root', passwd='123456', db='demodb', charset='utf8')
        cur = conn.cursor()
        #查询语句，将查询到的内容进行了计算，即（Xg_1 ^2) + （Yg_1 ^2);Xg_1:质心1的横坐标，Yg_1:质心1的纵坐标
        sql = "SELECT datetime,POW(centriod.Xg_1,2)+POW(centriod.Yg_1,2),POW(centriod.Xg_2,2)+POW(centriod.Yg_2,2) FROM centriod WHERE datetime BETWEEN '%s' AND '%s'" % (initTime, endTime)
        results = query_all(cur=cur, sql=sql, args=None)

        #方法1.直接使用日期作为横坐标，但是有问题，不能识别出来
        # second = SonWindow(self)
        # datetimes = np.array(results)[:,0]
        # print('*', datetimes)
        # data = np.array(results)[:,1]
        # data2 = np.array(results)[:,2]
        # datetimes = [datetime.timestamp(ddatetime) for ddatetime in datetimes]
        # print(datetimes,len(datetimes))
        # layout = pg.GraphicsLayout()
        # second.ui.graphicsView.addItem(layout)
        # plot = layout.addPlot(axisItems={'bottom': pg.DateAxisItem()})
        # plot.plot(datetimes[:], y=data, symbol='o',symbolPen=None, symbolSize=10)
        # second.setAttribute(Qt.WA_DeleteOnClose)
        # second.setWindowTitle("数据展示（右键可以保存图像）")
        # second.show()


        second = SonWindow(self)    #显示窗口，之所要创立新的展示窗口只要还是在原窗口显示有问题，只在界面的左上角一小块区域显示
        datetime = np.array(results)[:,0]    #查询到的results是元组，将其转化为 numpy 方便切片处理。
        datetime = [str(s) for s in datetime]    #datetime本来是datetime数据类型，这里将其转化为str类型
        data = np.array(results)[:,1]
        data2 = np.array(results)[:,2]
        pg.setConfigOption('background', 'w')    #设置pg的显示背景，改为白色
        pg.setConfigOption('foreground', 'k')
        print('绘制图像')

        xdict = dict(enumerate(datetime))   #将时间转化为字典类型
        stringaxis = pg.AxisItem(orientation='bottom')
        stringaxis.setTicks([list(xdict.items())[0:-1:int(len(xdict)/5)]]) #用于设置有几个横坐标，/5就代表只显示5个横坐标，有利有弊，没有找到自适应的坐标设置
        layout = pg.GraphicsLayout()    #设置布局
        second.ui.graphicsView.addItem(layout)    #为子窗口的graphicsView添加布局
        plot =layout.addPlot(axisItems={'bottom': stringaxis})   #为布局添加PlotItem（GraphicsView)
        plot.plot(list(xdict.keys()), data, symbol='o',symbolPen=None, symbolSize=10)
        second.setAttribute(Qt.WA_DeleteOnClose)    #关闭时自动删除
        second.setWindowTitle("数据展示（右键可以保存图像）")    #设置子窗口的标题名
        second.show()







if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MyMainWindow()
    w.show()
    app.exec_()

